#pragma once
#include "../Object.h"
#include "../Constants.h"
#include "../RenderDataCacheHelper.h"
#include "../../render/EShaderType.h"
#include "../../render/Uniform.h"
#include <map>
POCELAIN_NAMESPACE_BEGIN
class POCELAIN_EXPORT Material: public Object , public RenderDataCacheHelper
{
public:
    friend IRenderer;
    Material();
    virtual ~Material();
    virtual bool isMaterial() const override {return true;}
    virtual EObjectClass getObjectClass() const override {return EObjectClass::E_MATERIAL;}
    // bool getFog()const {return mFog;}
    // void setFog(bool val);

    GLenum getBlending() const { return mBlending;}
    void setBlending(GLenum val);

    GLenum getSide()const { return mSide; }
    void setSide(GLenum val);

    // bool getFlatShading() const { return mFlatShading;}
    // void setFlatShading(bool val);

    bool getVertexColors() const { return mVertexColors;}
    void setVertexColors(bool val);

    // Real getOpacity(){ return mOpacity;}
    // void setOpacity(Real val);

    bool getTransparent() const { return mTransparent; } 
    void setTransparent(bool val);

    GLenum getBlendSrc() const { return mBlendSrc; }
    void setBlendSrc(GLenum val);

    GLenum getBlendDst() const { return mBlendDst; }
    void setBlendDst(GLenum val);

    GLenum getBlendEquation() const { return mBlendEquation; }
    void setBlendEquation(GLenum val);

    GLenum getDepthFunc() const { return mDepthFunc; } 
    void setDepthFunc(GLenum val);

    bool getDepthTest() const { return mDepthTest; }
    void setDepthTest(bool val) ;

    bool getDepthWrite() const { return mDepthWrite; }
    void setDepthWrite(bool val);

    uint32_t getStencilWriteMask() const { return mStencilWriteMask; }
    void setStencilWriteMask(uint32_t val);

    GLenum getStencilFunc() const { return mStencilFunc; }
    void setStencilFunc(GLenum val);
    
    uint32_t getStencilFuncMask() const {  return mStencilFuncMask; }
    void setStencilFuncMask(uint32_t val);

    GLenum getStencilFail() const { return mStencilFail; }
    void setStencilFail(GLenum val);

    GLenum getStencilZFail() const { return mStencilZFail; }
    void setStencilZFail(GLenum val);

    GLenum getStencilZPass() const { return mStencilZPass; }
    void setStencilZPass(GLenum val);

    bool getStencilWrite() const { return mStencilWrite; }
    void setStencilWrite(bool val);

    bool getClipIntersection() const { return mClipIntersection; }
    void setClipIntersection(bool val);

    bool getClipShadows() const { return mClipShadows; } 
    void setClipShadows(bool val);

    bool getColorWrite() const { return mColorWrite; }
    void setColorWrite(bool val);
    
    bool getPolygonOffset() const { return mPolygonOffset; }
    void setPolygonOffset(bool val);

    Real getPolygonOffsetFactor () const { return mPolygonOffsetFactor; }
    void setPolygonOffsetFactor (Real val);

    Real getPolygonOffsetUnits() const { return mPolygonOffsetUnits; }
    void setPolygonOffsetUnits(Real val);

    bool getDithering() const { return mDithering; } 
    void setDithering(bool val);

    Real getAlphaTest() const { return mAlphaTest; }
    void setAlphaTest(bool val);

    bool getPremultipliedAlpha() const { return mPremultipliedAlpha; }
    void setPremultipliedAlpha(bool val);

    // bool getVisible() const { return mVisible; }
    // void setVisible(bool val);

    // bool getToneMapped() const { return mToneMapped; } 
    // void setToneMapped(bool val);

    bool getDirty() const { return mDirty ; }

    const std::map<std::string,RefPtr<IUniform>> &getNameUniformMap()const{return mMapNameUniform;}
    void setUniformByName(const std::string &name,IUniform *uniform);
    RefPtr<IUniform> getUniformByName(const std::string &name);
protected:
    bool mFog = true;
    GLenum mBlending = NormalBlending;
    GLenum mSide = FrontSide;
    bool mFlatShading = false;
    bool mVertexColors = false;
    Real mOpacity = 1.0;
    bool mTransparent = false;
    GLenum mBlendSrc = SrcAlphaFactor;
    GLenum mBlendDst = OneMinusSrcAlphaFactor;
    GLenum mBlendEquation = AddEquation;
    /* this.mBlendSrcAlpha = null; */
    /* this.mBlendDstAlpha = null; */
    /* this.mBlendEquationAlpha = null; */
    GLenum mDepthFunc = LessEqualDepth;
    bool mDepthTest = true;
    bool mDepthWrite = true;
    uint32_t mStencilWriteMask = 0xff;
    GLenum mStencilFunc = AlwaysStencilFunc;
    //this.mStencilRef = 0;
    uint32_t mStencilFuncMask = 0xff;
    GLenum mStencilFail = KeepStencilOp;
    GLenum mStencilZFail = KeepStencilOp;
    GLenum mStencilZPass = KeepStencilOp;
    bool mStencilWrite = false;
    //this.mClippingPlanes = null;
    bool mClipIntersection = false;
    bool mClipShadows = false;
    //this.mShadowSide = null;
    bool mColorWrite = true;
    //this.mPrecision = null; // override the renderer's default precision for this material
    bool mPolygonOffset = false;
    Real mPolygonOffsetFactor = 0;
    Real mPolygonOffsetUnits = 0;
    bool mDithering = false;
    Real mAlphaTest = 0;
    bool mPremultipliedAlpha = false;
    bool mVisible = true;
    bool mToneMapped = true;


protected:
    bool mDirty = true;
    std::map<std::string,RefPtr<IUniform>> mMapNameUniform;
};
POCELAIN_NAMESPACE_END
